package com.ctg.behavior.calc.impala.calculator;

import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.ctg.behavior.api.CtCalcStatus;
import com.ctg.behavior.calc.common.CtSQLParam;
import com.ctg.behavior.calc.impala.CtCalculator;
import com.ctg.behavior.calc.impala.builder.addictions.CtAddictionsTimesReportBuilder;
import com.ctg.behavior.calc.impala.builder.addictions.CtAddictionsTimesResultBuilder;
import com.ctg.behavior.calc.impala.engine.ImpalaSQLEngine;
import com.ctg.behavior.calc.impala.report.addictions.CtAddictionsTimesReport;
import com.ctg.behavior.calc.impala.transfer.addictions.CtAddictionsTimesTransfer;
import com.ctg.behavior.calc.impala.utils.CtCalculatorUtils;
import com.ctg.behavior.client.impala.common.CtQueryResult;
import com.ctg.behavior.common.addictions.CtAddictionsCalcBody;
import com.ctg.behavior.common.addictions.CtAddictionsCalcData;
import com.ctg.behavior.common.addictions.CtAddictionsCalcResult;
import com.ctg.behavior.common.calc.CtCalcBody;
import com.ctg.behavior.common.calc.CtCalcResult;
import com.ctg.behavior.common.consts.CtCalcConsts;
import com.ctg.behavior.common.consts.CtCalcTaskConsts;
import com.ctg.behavior.utils.CtDateUtils;
import com.ctg.behavior.utils.CtStatusUtils;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class CtAddictionsCalculator implements CtCalculator {

	@Autowired
	private CtAddictionsTimesReportBuilder timesReportBuilder;
	@Autowired
	private CtAddictionsTimesTransfer timesTransfer;
	@Autowired
	private CtAddictionsTimesResultBuilder timesResultBuilder;

	@Autowired
	private ImpalaSQLEngine sqlEngine;

	/****************************************************************
	 * @apiNote: 1.
	 */
	@Override
	public CtCalcResult doCalculator(CtCalcBody calcBody) {
		CtAddictionsCalcResult calcResult = new CtAddictionsCalcResult();
		if (!(calcBody instanceof CtAddictionsCalcBody)) {
			log.error("calcBody={}", calcBody.getClass());
			CtStatusUtils.fillStatus(calcResult, CtCalcStatus.BodyNoMatch);
			return calcResult;
		}
		CtAddictionsCalcData calcData = new CtAddictionsCalcData();
		calcResult.setValue(calcData);

		CtAddictionsCalcBody addictionsCalcBody = (CtAddictionsCalcBody) calcBody;

		if (CtCalcConsts.MEASURE_TYPE_TIMES.equals(addictionsCalcBody.getMeasureType())) {
			timesResultBuilder.resetResultBuilderTheadLocal();
			return this.doTimesCalculator(addictionsCalcBody);
		}

		return calcResult;
	}

	public CtAddictionsCalcResult doTimesCalculator(CtAddictionsCalcBody addictionsCalcBody) {

		CtAddictionsCalcResult calcResult = new CtAddictionsCalcResult();
		CtAddictionsCalcData calcData = new CtAddictionsCalcData();
		// 1. 通用字段
		calcData.setAppId(addictionsCalcBody.getAppId());
		calcData.setBookmarkId(addictionsCalcBody.getBookmarkId());
		calcData.setRequestId(addictionsCalcBody.getRequestId());
		calcData.setReportUpdateTime(CtDateUtils.dateToString(new Date()));
		calcData.setDataUpdateTime(calcData.getDataUpdateTime());
		// 2.
		calcData.setByField(addictionsCalcBody.getByField());

		calcResult.setValue(calcData);

		log.info("doBuilder-start: {}", CtDateUtils.getCurrentDateSSS());
		List<CtAddictionsTimesReport> reports = timesReportBuilder.doBuilder(addictionsCalcBody);
		log.info("doBuilder-end: {}", CtDateUtils.getCurrentDateSSS());

		// 2. 初始化ResultBuilder
		log.info("time - start: {}", CtDateUtils.getCurrentDateSSS());

		for (CtAddictionsTimesReport oneTimesReport : reports) {
			String oneTimesSQL = timesTransfer.doTransfer(oneTimesReport, CtSQLParam.createParam());
			String queryType = CtCalcTaskConsts.TASK_TYPE_ADDICTIONS;
			CtQueryResult queryResult = sqlEngine.doQuery(queryType, oneTimesSQL);
			log.info("queryResult={}", JSON.toJSONString(queryResult));
			
			CtCalculatorUtils.fillCalcResult(calcResult, queryResult);
			if (!calcResult.getSuccess()) {
				log.error(queryResult.getCode());
				return calcResult;
			}
			calcData = timesResultBuilder.doBuilder(calcData, queryResult.getRows(), oneTimesReport);
			log.info("calcData={}", JSON.toJSONString(calcData));
		}

		log.info("time - end: {}", CtDateUtils.getCurrentDateSSS());
		return calcResult;
	}

}
